from django.contrib.auth.backends import ModelBackend

from yubikey.decrypt import InvalidToken, InvalidAESKey

from models import Yubikey

class YubikeyBackend(ModelBackend):
    """
    This backend checks the token from a Yubikey. It does NOT check the
    password, the login view is responsible for that because it might be done
    in two steps.
    """    
    def authenticate(self, token=None):
        public_id = token[:-32]

        # check if token exists
        try:
            yubikey = Yubikey.objects.get(public_id=public_id)
        except Yubikey.DoesNotExist:
            return None

        # check if user and yubikey are active
        if not yubikey.is_active or not yubikey.user.is_active:
            return None

        # check if token is correct
        try:
            if not yubikey.check_token(token):
                return None
        except InvalidToken:
            return None
        except InvalidAESKey:
            return None
        else:
            return yubikey.user

class ModelBackendNoStaff(ModelBackend):
    """
    Example backend that can be used together with the YubikeyBackend to enforce
    that all staff members can not log in with just a password. In that case
    this backend should replace the default Django backend like this:

    AUTHENTICATION_BACKENDS = ( 
        ('yubikey.yubidjango.backends.YubikeyBackend'),
        ('yubikey.yubidjango.backends.ModelBackendNoStaff'),
    )
    """
    def authenticate(self, *args, **kwargs):
        user = super(ModelBackendNoStaff, self).authenticate(*args, **kwargs)
        if user and (user.is_staff or user.is_superuser):
            return None
        else:
            return user

class ModelBackendNoYubikey(ModelBackend):
    """
    Example backend that can be used together with the YubikeyBackend to enforce
    that all users with at least one active Yubikey can not log in with just a
    password. This backend should replace the default Django backend like this:

    AUTHENTICATION_BACKENDS = ( 
        ('yubikey.yubidjango.backends.YubikeyBackend'),
        ('yubikey.yubidjango.backends.ModelBackendNoYubikey'),
    )
    """
    def authenticate(self, *args, **kwargs):
        user = super(ModelBackendNoYubikey, self).authenticate(*args, **kwargs)
        if user and user.yubikey_set.filter(is_active=True).count():
            return None
        else:
            return user
